package com.ti.shangou.config.shiro;

import com.ti.shangou.pojo.entity.Merchant;
import com.ti.shangou.pojo.entity.User;
import com.ti.shangou.pojo.query.UserQuery;
import com.ti.shangou.pojo.vo.PermissionVO;
import com.ti.shangou.pojo.vo.RoleVO;
import com.ti.shangou.pojo.vo.UserVO;
import com.ti.shangou.service.UserService;
import com.ti.shangou.service.impl.MerchantServiceImpl;
import com.ti.shangou.service.impl.PermissionServiceImpl;
import com.ti.shangou.service.impl.RoleServiceImpl;
import com.ti.shangou.service.impl.UserServiceImpl;
import com.ti.shangou.util.Permission.SetPermission;
import com.ti.shangou.util.net.NetUtil;
import com.ti.shangou.util.password.PasswordUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * creator：Administrator
 * date:2019/10/22
 * shiro认证和授权的 一个类（领域类）
 */

public class UserRealm extends AuthorizingRealm {
    Logger logger = LoggerFactory.getLogger(UserRealm.class);

    @Resource
    MerchantServiceImpl merchantService;
    @Resource
    UserServiceImpl userService;
    @Resource
    RoleServiceImpl roleService;
    @Resource
    PermissionServiceImpl permissionService;

    /**
     * 认证身份用的
     * subject.login(token)调用之后，会进入到这个方法
     *
     * @param authenticationToken 携带了用户名和密码的：认证，判断用户名和密码跟数据库里边是否一致
     * @return
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        Object principal = authenticationToken.getPrincipal();// 获取身份（用户名）
        Object credentials = authenticationToken.getCredentials();// 获取密码（密码）：是前端传递来的，不具备真实性；这里传来的是字符数组

        String password = new String((char[]) credentials);// 前端传递过来的// String.valueOf((char[]) credentials)
        String encodePassword = PasswordUtil.encodePassword(password);
        UserQuery query = new UserQuery();
        Session session = SecurityUtils.getSubject().getSession();
        Object code = session.getAttribute("code");
        List<RoleVO> hisRoles ;     // 准备角色集合
        UserVO userVO = null;   // 准备用户
        // 开始判断是密码还是短信登录
        if (!StringUtils.isEmpty(code)){
            // 短信登录方式
            Object loginCode = session.getAttribute("loginCode"); // 后台发送的验证码
            System.out.println(loginCode);
            if (code.equals(loginCode)){
                query.setPhone((String)principal);
                userVO = userService.selectUserByPhone(query);
                // 因为已判断手机号存在所以直接存
                session.setAttribute("userId", userVO.getUserId());
                session.setAttribute("nickName", userVO.getNickName());
                session.setAttribute("phone", userVO.getPhone());
                // 设置角色
                hisRoles = roleService.selectRoleListByUserRoles(userVO.getRoles());
            }else {
                throw new CredentialsException("验证码错误");
            }
        }
        else { // 密码方式登录
            query.setPhone((String)principal);
            query.setPassword(PasswordUtil.encodePassword(password));
            userVO = userService.passwordLogin(query);
            if (userVO==null){
                throw new UnknownAccountException("账户或密码错误");
            }else { // 表用户存在
                session.setAttribute("userId", userVO.getUserId());
                session.setAttribute("nickName", userVO.getNickName());
                session.setAttribute("phone", userVO.getPhone());
                // 设置角色
                hisRoles = roleService.selectRoleListByUserRoles(userVO.getRoles());
            }
        }

        // 设置session
        if (!StringUtils.isEmpty(hisRoles)){
            List<PermissionVO> permissionVOS = permissionService.selectPermissionsByRoles(hisRoles);
            List<RoleVO> roleVOS = SetPermission.setPermissionsOfRoles(hisRoles, permissionVOS);
            session.setAttribute("hisRoles",roleVOS);
            session.setAttribute("user",userVO);
        }

        User u = new User();
        u.setUserId(userVO.getUserId());
        u.setLastLoginIp(NetUtil.getIpAddr());  // 设置登录Ip
        u.setLastLoginTime(new Date());     // 设置最后登录时间
        userService.updateUser(u);

        return new SimpleAuthenticationInfo(authenticationToken.getPrincipal(), authenticationToken.getCredentials(), "userRealm");
    }

    /**
     * 对身份进行授权用的
     * @param principalCollection
     * @return
     * @throws AuthenticationException 根据用户名去数据库查询这个 用户的角色和权限设置给 这个SimpleAuthorizationInfo对象即可
     *                                 <p>
     *                                 只有第一次判断的时候，才能进入授权方法，如果当前用户没有这个权限或者角色，那么将会被缓存到内存之中，第二次之后，就不用查询了
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {// 登录成功之后，给用户授予角色和权限用的，或者说检测用户的角色和权限的
        SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();

        return auth;

    }

}
